import { throttle } from "lodash";
import { DrawerMesh } from "./Mesh/drawer";
import { BaseOptions } from "./type";

const defaultBaseOptions:BaseOptions = {
    currentScale: 1,
    minScale: 0.5,
    maxScale: 4,
};
export const definedOptions = (options: Partial<BaseOptions>): BaseOptions=>{
    return {
        ...defaultBaseOptions,
        ...options,
    };
} 

export class TzFlow {
    dom: HTMLElement;

    canvas?: HTMLCanvasElement;
    ctx?: CanvasRenderingContext2D;

    width: number = 0;
    height: number = 0;

    options: BaseOptions;

    // 鼠标位置
    mousePos: {x:number, y:number} = {x:0, y:0};

    // 鼠标是否按下
    mouseDown: boolean = false;

    constructor(dom, optionsConfig:Partial<BaseOptions>){
        this.dom = dom;

        this.options = definedOptions({
            ...optionsConfig,
            _width: dom.clientWidth,
            _height: dom.clientHeight,
        });
    }

    // 初始化函数
    private _init(){
        if( this.dom.querySelector('canvas') ) return false;

        // 创建canvas元素
        const canvas = document.createElement('canvas');
        this.height = this.options._height = canvas.height = this.dom.clientHeight;
        this.width = this.options._width = canvas.width = this.dom.clientWidth;
        this.dom.appendChild(canvas);

        this.canvas = canvas;
        this.ctx = canvas.getContext('2d');
    }

    private _render(){
        this._clear();
        (new DrawerMesh(this.canvas, this.options)).render(this.options);
    }
    private _clear(){
        const {e,f} = this.ctx.getTransform();
        const x = (0-e)/this.options.currentScale;
        const y = (0-f)/this.options.currentScale;
        const w = (this.options._width + Math.abs(e))/this.options.currentScale;
        const h = (this.options._height + Math.abs(f))/this.options.currentScale;
        this.ctx!.clearRect(x, y, w, h);
    }

    // 初始化监听事件
    private _initListen(){
        // 监听鼠标滚轮事件
        this.canvas && this.canvas.addEventListener('wheel',(event)=>{
            this._clear();
            if( event.deltaY <= 0 ){
                if( this.options.currentScale < this.options.maxScale  ){
                    this.options.currentScale *= 2;
                    this.ctx!.scale(2,2);
                }
            }else{
                if( this.options.currentScale > this.options.minScale ){
                    this.options.currentScale /= 2;
                    this.ctx!.scale(0.5,0.5);
                }
            }
            this._render();
        });

        // 监听鼠标移动事件
        this.canvas && this.canvas.addEventListener('mousemove', throttle( 
            (event)=>{
                const { clientX, clientY } = event;

                if( this.mouseDown ){
                    this._clear();
                    let { e, f } = this.ctx.getTransform();
                    let moveX = (clientX - this.mousePos.x);
                    let moveY = (clientY - this.mousePos.y);
                    this.ctx!.translate(moveX, moveY);
                    this._render();
                }

                this.mousePos = {x:clientX, y:clientY};
            },10)
        );

        // 监听鼠标点击事件
        this.canvas && this.canvas.addEventListener('click',(event)=>{
            const { clientX, clientY } = event;
            // this.mousePos = {x:clientX, y:clientY};
        });

        // 监听鼠标按下事件
        this.canvas && this.canvas.addEventListener('mousedown',(event)=>{
            this.mouseDown = true;
        });

        // 监听鼠标松开事件
        this.canvas && this.canvas.addEventListener('mouseup',(event)=>{
            const { clientX, clientY } = event;
            this.mouseDown = false;
            // this.mousePos = {x:clientX, y:clientY};
        })
    }

    start(){
        if( !this.dom ){
            console.error('TzFlow: dom is not defined');
            return false;
        }

        this._init();
        

        if( !this.canvas ){
            console.error('TzFlow: canvas is not defined');
            return false;
        }

        this._render();

        this._initListen();
    }
}